#include "stdafx.h"
#include "pyhgeParticleSystemInfo.h"
#include "pyhgeSprite.h"
PyTypeObject ParticleSystemInfoType = {
	PyObject_HEAD_INIT(NULL)
	0,                         /*ob_size*/
	"hge.ParticleSystemInfo",             /*tp_name*/
	sizeof(pyParticleSystemInfo), /*tp_basicsize*/
	0,                         /*tp_itemsize*/
	0,                         /*tp_dealloc*/
	0,                         /*tp_print*/
	0,                         /*tp_getattr*/
	0,                         /*tp_setattr*/
	0,                         /*tp_compare*/
	0,                         /*tp_repr*/
	0,                         /*tp_as_number*/
	0,                         /*tp_as_sequence*/
	0,                         /*tp_as_mapping*/
	0,                         /*tp_hash */
	0,                         /*tp_call*/
	0,                         /*tp_str*/
	0,                         /*tp_getattro*/
	0,                         /*tp_setattro*/
	0,                         /*tp_as_buffer*/
	Py_TPFLAGS_DEFAULT,        /*tp_flags*/
	"ParticleSystemInfo structure is used to define all particle system parameters",/* tp_doc */
};
/*
static PyMemberDef ParticleSystemInfo_members[] = {
	{"nEmission",T_INT,offsetof(pyParticleSystemInfo,psi->nEmission),0,""},
	{"fLifetime",T_FLOAT,offsetof(pyParticleSystemInfo,psi->fLifetime),0,""},

	{"fParticleLifeMin",T_FLOAT,offsetof(pyParticleSystemInfo,psi->fParticleLifeMin),0,""},
	{"fParticleLifeMax",T_FLOAT,offsetof(pyParticleSystemInfo,psi->fParticleLifeMax),0,""},

	{"fDirection",T_FLOAT,offsetof(pyParticleSystemInfo,psi->fDirection),0,""},
	{"fSpread",T_FLOAT,offsetof(pyParticleSystemInfo,psi->fSpread),0,""},
	//bool bRelative

	{"fSpeedMin",T_FLOAT,offsetof(pyParticleSystemInfo,psi->fSpeedMin),0,""},
	{"fSpeedMax",T_FLOAT,offsetof(pyParticleSystemInfo,psi->fSpeedMax),0,""},

	{"fGravityMin",T_FLOAT,offsetof(pyParticleSystemInfo,psi->fGravityMin),0,""},
	{"fGravityMax",T_FLOAT,offsetof(pyParticleSystemInfo,psi->fGravityMax),0,""},

	{"fRadialAccelMin",T_FLOAT,offsetof(pyParticleSystemInfo,psi->fRadialAccelMin),0,""},
	{"fRadialAccelMax",T_FLOAT,offsetof(pyParticleSystemInfo,psi->fRadialAccelMax),0,""},

	{"fTangentialAccelMin",T_FLOAT,offsetof(pyParticleSystemInfo,psi->fTangentialAccelMin),0,""},
	{"fTangentialAccelMax",T_FLOAT,offsetof(pyParticleSystemInfo,psi->fTangentialAccelMax),0,""},

	{"fSizeStart",T_FLOAT,offsetof(pyParticleSystemInfo,psi->fSizeStart),0,""},
	{"fSizeEnd",T_FLOAT,offsetof(pyParticleSystemInfo,psi->fSizeEnd),0,""},
	{"fSizeVar",T_FLOAT,offsetof(pyParticleSystemInfo,psi->fSizeVar),0,""},
	
	{"fSpinStart",T_FLOAT,offsetof(pyParticleSystemInfo,psi->fSpinStart),0,""},
	{"fSpinEnd",T_FLOAT,offsetof(pyParticleSystemInfo,psi->fSpinEnd),0,""},
	{"fSpinVar",T_FLOAT,offsetof(pyParticleSystemInfo,psi->fSpinVar),0,""},

	{"colColorStart",T_UINT,offsetof(pyParticleSystemInfo,psi->colColorStart),0,""},
	{"colColorEnd",T_UINT,offsetof(pyParticleSystemInfo,psi->colColorEnd),0,""},
	{"fColorVar",T_FLOAT,offsetof(pyParticleSystemInfo,psi->fColorVar),0,""},
	{"fAlphaVar",T_FLOAT,offsetof(pyParticleSystemInfo,psi->fAlphaVar),0,""},
	{NULL}  
};*/
//closure is offset of psi
static PyObject * 
_ParticleSystemInfo_GetFloatInfo(PyObject * _self,void * closure)
{
	pyParticleSystemInfo * self = (pyParticleSystemInfo*)_self;
	char * addr = (char*)self->psi;
	addr += (int)closure;
	return PyFloat_FromDouble((double)*(float*)addr);
}
_ParticleSystemInfo_SetFloatInfo(PyObject * _self, PyObject *value, void *closure)
{
	pyParticleSystemInfo * self = (pyParticleSystemInfo*)_self;
	char * addr = (char*)self->psi;
	addr += (int)closure;
	double val = PyFloat_AsDouble(value);
	if (val == -1 && PyErr_Occurred()) return -1;
	*(float*)addr = (float)val;
	return 0;
}

static PyObject * 
_ParticleSystemInfo_GetIntInfo(PyObject * _self,void * closure)
{
	pyParticleSystemInfo * self = (pyParticleSystemInfo*)_self;
	char * addr = (char*)self->psi;
	addr += (int)closure;
	return PyInt_FromLong(*(int*)addr);
}
_ParticleSystemInfo_SetIntInfo(PyObject * _self, PyObject *value, void *closure)
{
	pyParticleSystemInfo * self = (pyParticleSystemInfo*)_self;
	char * addr = (char*)self->psi;
	addr += (int)closure;
	int val = PyInt_AsLong(value);
	if (val == -1 && PyErr_Occurred()) return -1;
	*(int*)addr = (int)val;
	return 0;
}


//sprite
static PyObject *
ParticleSystemInfo_getsprite(PyObject * _self,void * closure)
{
	pyParticleSystemInfo * self = (pyParticleSystemInfo*)_self;
	if (self->sprite)
	{
		Py_INCREF(self->sprite);
		return (PyObject*)self->sprite;
	}
	Py_RETURN_NONE;
}

static int
ParticleSystemInfo_setsprite(PyObject * _self, PyObject *value, void *closure)
{
	pyParticleSystemInfo * self = (pyParticleSystemInfo*)_self;
	if (value == NULL) 
	{
		PyErr_SetString(PyExc_TypeError, "Cannot delete the sprite attribute.");
		return -1;
	}
	if (!PyObject_TypeCheck(value,&SpriteType))
	{
		PyErr_SetString(PyExc_TypeError,"Sprite object is required.");
		return -1;
	}
	pySprite * spr = (pySprite*)value;
	self->psi->sprite = spr->phgeSprite;
	Py_INCREF(spr);
	Py_XDECREF(self->sprite);
	self->sprite = spr;
	return 0;
}
//bRelative
static PyObject *
ParticleSystemInfo_getbRelative(PyObject * _self,void * closure)
{
	pyParticleSystemInfo * self = (pyParticleSystemInfo*)_self;
	if (self->psi->bRelative)
	{
		Py_RETURN_TRUE;
	}
	else
	{
		Py_RETURN_FALSE;
	}
}

static int
ParticleSystemInfo_setbRelative(PyObject * _self, PyObject *value, void *closure)
{
	pyParticleSystemInfo * self = (pyParticleSystemInfo*)_self;
	if (value == NULL)
	{
		PyErr_SetString(PyExc_TypeError, "Cannot delete the bRelative attribute.");
		return -1;
	}
	int bval = PyObject_IsTrue(value);
	if (bval == -1) return -1;
	self->psi->bRelative = bval > 0;
	return 0;
}

static PyGetSetDef ParticleSystemInfo_getseters[] = {
	{"sprite",ParticleSystemInfo_getsprite, ParticleSystemInfo_setsprite,"",NULL},
	{"bRelative",ParticleSystemInfo_getbRelative, ParticleSystemInfo_setbRelative,"",NULL},

	{"nEmission",_ParticleSystemInfo_GetIntInfo,_ParticleSystemInfo_SetIntInfo,"",(void*)offsetof(hgeParticleSystemInfo,nEmission)},
	{"fLifetime",_ParticleSystemInfo_GetFloatInfo,_ParticleSystemInfo_SetFloatInfo,"",(void*)offsetof(hgeParticleSystemInfo,fLifetime)},

	{"fParticleLifeMin",_ParticleSystemInfo_GetFloatInfo,_ParticleSystemInfo_SetFloatInfo,"",(void*)offsetof(hgeParticleSystemInfo,fParticleLifeMin)},
	{"fParticleLifeMax",_ParticleSystemInfo_GetFloatInfo,_ParticleSystemInfo_SetFloatInfo,"",(void*)offsetof(hgeParticleSystemInfo,fParticleLifeMax)},

	{"fDirection",_ParticleSystemInfo_GetFloatInfo,_ParticleSystemInfo_SetFloatInfo,"",(void*)offsetof(hgeParticleSystemInfo,fDirection)},
	{"fSpread",_ParticleSystemInfo_GetFloatInfo,_ParticleSystemInfo_SetFloatInfo,"",(void*)offsetof(hgeParticleSystemInfo,fSpread)},
	
	{"fSpeedMin",_ParticleSystemInfo_GetFloatInfo,_ParticleSystemInfo_SetFloatInfo,"",(void*)offsetof(hgeParticleSystemInfo,fSpeedMin)},
	{"fSpeedMax",_ParticleSystemInfo_GetFloatInfo,_ParticleSystemInfo_SetFloatInfo,"",(void*)offsetof(hgeParticleSystemInfo,fSpeedMax)},

	{"fGravityMin",_ParticleSystemInfo_GetFloatInfo,_ParticleSystemInfo_SetFloatInfo,"",(void*)offsetof(hgeParticleSystemInfo,fGravityMin)},
	{"fGravityMax",_ParticleSystemInfo_GetFloatInfo,_ParticleSystemInfo_SetFloatInfo,"",(void*)offsetof(hgeParticleSystemInfo,fGravityMax)},

	{"fRadialAccelMin",_ParticleSystemInfo_GetFloatInfo,_ParticleSystemInfo_SetFloatInfo,"",(void*)offsetof(hgeParticleSystemInfo,fRadialAccelMin)},
	{"fRadialAccelMax",_ParticleSystemInfo_GetFloatInfo,_ParticleSystemInfo_SetFloatInfo,"",(void*)offsetof(hgeParticleSystemInfo,fRadialAccelMax)},

	{"fTangentialAccelMin",_ParticleSystemInfo_GetFloatInfo,_ParticleSystemInfo_SetFloatInfo,"",(void*)offsetof(hgeParticleSystemInfo,fTangentialAccelMin)},
	{"fTangentialAccelMax",_ParticleSystemInfo_GetFloatInfo,_ParticleSystemInfo_SetFloatInfo,"",(void*)offsetof(hgeParticleSystemInfo,fTangentialAccelMax)},

	{"fSizeStart",_ParticleSystemInfo_GetFloatInfo,_ParticleSystemInfo_SetFloatInfo,"",(void*)offsetof(hgeParticleSystemInfo,fSizeStart)},
	{"fSizeEnd",_ParticleSystemInfo_GetFloatInfo,_ParticleSystemInfo_SetFloatInfo,"",(void*)offsetof(hgeParticleSystemInfo,fSizeEnd)},
	{"fSizeVar",_ParticleSystemInfo_GetFloatInfo,_ParticleSystemInfo_SetFloatInfo,"",(void*)offsetof(hgeParticleSystemInfo,fSizeVar)},
	
	{"fSpinStart",_ParticleSystemInfo_GetFloatInfo,_ParticleSystemInfo_SetFloatInfo,"",(void*)offsetof(hgeParticleSystemInfo,fSpinStart)},
	{"fSpinEnd",_ParticleSystemInfo_GetFloatInfo,_ParticleSystemInfo_SetFloatInfo,"",(void*)offsetof(hgeParticleSystemInfo,fSpinEnd)},
	{"fSpinVar",_ParticleSystemInfo_GetFloatInfo,_ParticleSystemInfo_SetFloatInfo,"",(void*)offsetof(hgeParticleSystemInfo,fSpinVar)},
	
	{"colColorStart",_ParticleSystemInfo_GetFloatInfo,_ParticleSystemInfo_SetFloatInfo,"",(void*)offsetof(hgeParticleSystemInfo,colColorStart)},
	{"colColorEnd",_ParticleSystemInfo_GetFloatInfo,_ParticleSystemInfo_SetFloatInfo,"",(void*)offsetof(hgeParticleSystemInfo,colColorEnd)},
	{"fColorVar",_ParticleSystemInfo_GetFloatInfo,_ParticleSystemInfo_SetFloatInfo,"",(void*)offsetof(hgeParticleSystemInfo,fColorVar)},
	{"fAlphaVar",_ParticleSystemInfo_GetFloatInfo,_ParticleSystemInfo_SetFloatInfo,"",(void*)offsetof(hgeParticleSystemInfo,fAlphaVar)},
	
	{NULL}  /* Sentinel */
};

//others
static PyObject *
ParticleSystemInfo_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
	pyParticleSystemInfo * self = (pyParticleSystemInfo*)type->tp_alloc(type, 0);
	if (!self) return NULL;
	ZeroMemory(&self->hold_psi,sizeof(self->hold_psi));
	self->psi = &self->hold_psi;
	self->sprite = NULL;
	self->refobj = NULL;
	return (PyObject*)self;
}
static void
ParticleSystemInfo_dealloc(PyObject * _self)
{
	pyParticleSystemInfo * self = (pyParticleSystemInfo*)_self;
	Py_XDECREF(self->sprite);
	Py_XDECREF(self->refobj);
	self->ob_type->tp_free((PyObject*)self);
}

static int
ParticleSystemInfo_init(PyObject *_self, PyObject *args, PyObject *kwds)
{
	static char *kwlist[] = {0};
	if (!PyArg_ParseTupleAndKeywords(args, kwds, ":ParticleSystemInfo", kwlist))
		return -1;
	return 0;
}
int pyParticleSystemInfo_AttachSprite(PyObject * self,pySprite * sprite,bool updateRealInfo)
{
	//sprite can be NULL.(to detach)
	if (PyObject_TypeCheck(self,&ParticleSystemInfoType))
	{
		pyParticleSystemInfo * _self = (pyParticleSystemInfo*)self;
		Py_XINCREF(sprite);
		Py_XDECREF(_self->sprite);
		_self->sprite = sprite;
		if (updateRealInfo) _self->psi->sprite = sprite?(sprite->phgeSprite):(NULL);
		return 0;
	}
	else
	{
		PyErr_SetString(PyExc_TypeError,"ParticleSystemInfo type is required.");
		return -1;
	}
}
int
pyParticleSystemInfo_BindInfo(PyObject * _self,hgeParticleSystemInfo * psi,PyObject * refobj)
{
	if (PyObject_TypeCheck(_self,&ParticleSystemInfoType))
	{
		pyParticleSystemInfo * self = (pyParticleSystemInfo*)_self;
		Py_XDECREF(self->refobj);
		if (PyErr_Occurred())
		{
			return -1;
		}
		Py_XINCREF(refobj);
		self->psi = psi;
		self->refobj = refobj;
		return 0;
	}
	else
	{
		PyErr_SetString(PyExc_TypeError,"ParticleSystemInfo type is required.");
		return -1;
	}
}
extern pyParticleSystemInfo *
pyNewParticleSystemInfo(hgeParticleSystemInfo * ppsi,pySprite * sprite)
{
	pyParticleSystemInfo * self = (pyParticleSystemInfo *)ParticleSystemInfo_new(&ParticleSystemInfoType,0,0);
	if (!self) return NULL;
	*(self->psi) = *ppsi;
	self->sprite = sprite;
	Py_XINCREF(sprite);
	return self;
}
extern int
pyInitParticleSystemInfo(PyObject * mod)
{
//	ParticleSystemInfoType.tp_members = ParticleSystemInfo_members;
	ParticleSystemInfoType.tp_getset = ParticleSystemInfo_getseters;
	ParticleSystemInfoType.tp_new = ParticleSystemInfo_new;
	ParticleSystemInfoType.tp_dealloc = ParticleSystemInfo_dealloc;
	ParticleSystemInfoType.tp_init = ParticleSystemInfo_init;
	if (PyType_Ready(&ParticleSystemInfoType) < 0) return -1;
	Py_INCREF(&ParticleSystemInfoType);
	return PyModule_AddObject(mod, "ParticleSystemInfo", (PyObject *)&ParticleSystemInfoType);
}